使用v

您所在的位置:网站首页 v-model 自定义组件 使用v

使用v

2023-04-13 13:13| 来源: 网络整理| 查看: 265

一、组件使用场景及需求分析~ 表单多个固定单值的情况,我们不用再去input框输入值,直接在固定的值里面去选择 选择以后父组件绑定的值对应改变,使得不需要发送表单前再进行赋值 选择前后,列表都是不可见的 二、开始我们的coding 首先我们需要的是一个有所有单值选项的list展示 然后是一个展示当前选择的文字框

像这样的: 这一步我们只需要父组件传递单值代码,然后当前选中的一个值,没有的话就默认为空。

vue:

 {{item.name}} 复制代码

JS:

props: { list: { type: Array, required: true, }, selected: Object, }, data() { return { scoped: { // 当前选中的 selected: this.selected, }, }; }, 复制代码

CSS:

.fd-select-box { position: relative; width: 200px; padding-right: 40px; padding-left: 10px; height: 36px; margin: 30px auto; line-height: 36px; border: 1px solid #41b883; border-radius: 4px; color: #000; font-size: 14px; text-align: left; cursor: pointer; box-sizing: border-box; .fd-arrow { position: absolute; top: 0; right: 0; font-size: 30px; transition: all 200ms; &.fd-down { transform: rotate(180deg); } } .fd-select-list { position: absolute; width: 100%; max-height: 200px; overflow: auto; list-style: none; top: 36px; left: 0; background: #fff; box-shadow: 0 0 5px rgba(0,0,0,0.2); z-index: 9; li { padding-left: 12px; line-height: 30px; cursor: pointer; &:hover { background: rgba(65, 191, 138, 0.2); } &.active { background: rgba(65, 191, 138, 0.9); color: #fff; } } } } 复制代码

这样,我们已经把外层框架搭建好了。

接下来,解决子组件改变,父组件对应的值发生改变。

一般情况我们会想到子组件把当前选中的值通过this.$emit传给父组件,然后父组件再在对应方法里面给对应的值赋值。今天我们用另外一种方法来解决这个问题,那就是v-model,相信我,用了它你会爱上它。

好了,我们看看官方文档怎么说的:

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:

model: { prop: 'checked', event: 'change' }, props: { checked: Boolean }, template: ` ` }) 复制代码

cn.vuejs.org/v2/guide/co…

我的理解就是提供了v-model;在自定义组件上model里的prop里的字段的值会直接赋给props里面对应字段,像之前我们给checked传值是在父组件上通过:checked='false'这样一种形式。现在我们可以使用v-model='false'。来看具体在select框里面的表现吧。

export default { name: 'fdSselect', model: { prop: 'selected', event: 'changeValue', }, props: { list: { type: Array, required: true, }, selected: Object, }, data() { return { scoped: { // 是否展示下面的列表 showFlag: false, // 当前选中的 selected: this.selected, }, }; }, methods: { // 值改变后传给父组件,因为组件定义了model,所以父组件相当于执行了绑定的model值=emit出去的值 changeValue(item) { this.scoped.selected = item; this.scoped.showFlag = false; this.$emit('changeValue', this.scoped.selected); }, }, }; 复制代码

父组件调用:

复制代码

上面的event是我们要emit出去的事件名。这一步相当于在父组件执行了父组件的this.selected等于子组件的this.scoped.selected;所以其实你用组件的时候v-model="value" 其实就是 :value="value" @change="(val) => {value = val}";

现在看看我们实现的效果:

前两个需求已经实现了,最后一个需求是在交互上的优化。

首先他要一开始的时候不展示,我们给一个控制下拉框显隐的变量。showFlag默认值为false;点击输入框时展开下拉列表。然后选中选项后隐藏下拉列表。

注意我们的页面结构,下拉列表是输入框的子元素,所以点击下拉列表元素的时候会涉及到事件冒泡,这个时候我们使用.stop修饰符来组织时间冒泡导致下拉列表一直不能隐藏。 vue:

       

                                           {{item.name}}         复制代码

JS:

// 值改变后传给父组件,因为组件定义了model,所以父组件相当于执行了绑定的model值=emit出去的值 changeValue(item) { this.scoped.selected = item; this.scoped.showFlag = false; this.$emit('changeValue', this.scoped.selected); }, // 改变下拉选项的显隐 changeShow() { this.scoped.showFlag = !this.scoped.showFlag; }, 复制代码

继续优化,我们现在实现了组件列表的显隐,但是只有操作当前组件时可以控制。那么我们点击其他地方的时候,其实也是希望组件列表可以隐藏起来的。

实现这个的思路:绑定一个点击事件在页面上,只要点击的元素不是当前组件,那么我们就可以隐藏当前组件的列表。这里我用到了自定义指令,具体实现如下:

clickOutside: { bind(el, binding) { function clickHandler(e) { // 这里判断点击的元素是否是本身,是本身,则返回 if (el.contains(e.target)) { return false; } // 判断指令中是否绑定了函数 if (binding.expression) { // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法 binding.value(e); } return true; } // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听 el.vueClickOutside = clickHandler; document.addEventListener('click', clickHandler); }, unbind(el) { // 解除事件监听 document.removeEventListener('click', el.vueClickOutside); delete el.vueClickOutside; }, }, 复制代码

最后实现效果如图:

后期待优化:实现可搜索的下拉框-->实现可以远程搜索的下拉框

以上为个人编写,希望能对大家的项目有所帮助,如有不当以及有更好的方法欢迎交流。

项目地址: github.com/jasminezx/s…



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3